﻿// <copyright file="CardControlErrorHandler.cs" company="SharpSTS">
// Copyright (c) 2007, 2008 All Right Reserved, http://sharpsts.com/
//
// This source is subject to the Microsoft Permissive License.
// Please see the License.txt file for more information.
// All other rights reserved.
//
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY 
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// </copyright>
// <author>Barry Dorrans</author>
// <email>barryd@idunno.org</email>
// <date>2008-06-24</date>
// <summary>Handles errors for the card control service and sends detailed or simple faults according to the STS configuration.</summary>

namespace SharpSTS.CardControl
{
    using System;
    using System.Collections.Generic;
    using System.ServiceModel;
    using System.ServiceModel.Channels;
    using System.ServiceModel.Dispatcher;

    using SharpSTS.Configuration;
    using SoapConstants = SharpSTS.Constants.Soap;

    using Properties;

    /// <summary>
    /// Handles errors for the card control service and sends detailed or simple faults according to the STS configuration.
    /// </summary>
    internal class CardControlErrorHandler : IErrorHandler
    {
        /// <summary>
        /// A lookup table for <see cref="ExceptionHandler"/>s.
        /// </summary>
        private static readonly Dictionary<Type, ExceptionHandler> marshallers = 
            new Dictionary<Type, ExceptionHandler> 
            {
                { typeof(System.Configuration.ConfigurationErrorsException), MarshallConfigurationExceptions },
                { typeof(NotImplementedException), MarshallNotImplementedExceptions }
            };

        /// <summary>
        /// Marshals an exception into a strong SOAP message fault.
        /// </summary>
        /// <param name="error">The exception to marshal.</param>
        /// <returns>A SOAP message fault, which is specified as part of the contract for <see cref="ICardControlService"/>.</returns>
        private delegate MessageFault ExceptionHandler(Exception error);

        /// <summary>
        /// Enables the creation of a custom <see cref="T:System.ServiceModel.FaultException`1"/> that is returned from an exception in the course of a service method.
        /// </summary>
        /// <param name="error">The <see cref="T:System.Exception"/> object thrown in the course of the service operation.</param>
        /// <param name="version">The SOAP version of the message.</param>
        /// <param name="fault">The <see cref="T:System.ServiceModel.Channels.Message"/> object that is returned to the client, or service, in the duplex case.</param>
        public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
        {
            FaultException<CardControlFault> basicFault =
                new FaultException<CardControlFault>(new CardControlFault(), Resources.ErrorFaultOccurred);

            MessageFault messageFault = basicFault.CreateMessageFault();
            
            if (STSSettings.Settings.UseDetailedFaultsForCardControl)
            {
                ExceptionHandler handler;
                if (marshallers.TryGetValue(error.GetType(), out handler))
                {
                    messageFault = handler(error);
                }
            }

            fault = Message.CreateMessage(version, messageFault, SoapConstants.FaultCodes.Action);
        }

        /// <summary>
        /// Enables error-related processing and returns a value that indicates whether subsequent HandleError implementations are called.
        /// </summary>
        /// <param name="error">The exception thrown during processing.</param>
        /// <returns>
        /// true if subsequent <see cref="T:System.ServiceModel.Dispatcher.IErrorHandler"/> implementations must not be called; otherwise, false. The default is false.
        /// </returns>
        public bool HandleError(Exception error)
        {
            return marshallers.ContainsKey(error.GetType());
        }

        /// <summary>
        /// Marshals an configuration exception into a strong SOAP message fault.
        /// </summary>
        /// <param name="error">The exception to marshal.</param>
        /// <returns>A SOAP message fault, which is specified as part of the contract for <see cref="ICardControlService"/>.</returns>
        private static MessageFault MarshallConfigurationExceptions(Exception error)
        {
            FaultException<ConfigurationFault> fault = new FaultException<ConfigurationFault>(
                                                             new ConfigurationFault(),
                                                             error.Message);
            return fault.CreateMessageFault();
        }

        /// <summary>
        /// Marshals an not implemented exception into a strong SOAP message fault.
        /// </summary>
        /// <param name="error">The exception to marshal.</param>
        /// <returns>A SOAP message fault, which is specified as part of the contract for <see cref="ICardControlService"/>.</returns>
        private static MessageFault MarshallNotImplementedExceptions(Exception error)
        {
            FaultException<NotImplementedFault> fault = new FaultException<NotImplementedFault>(
                                                             new NotImplementedFault());
            return fault.CreateMessageFault();
        }
    }
}
